/**
 * Created by xinxinran on 2017/8/22.
 */
'use strict';
const net = require('net'),
    loggerUtil = require('../utils/loggerUtil'),
    beanUtil = require('../utils/beanUtil'),
    ClientManager = require('./client-manager'),
    Router = require('./router');

class SocketServer {
    constructor(conf){
        let connListener, _this = this, logger = loggerUtil.getLogger();
        if(typeof conf === 'function') {
            connListener = conf;
            conf = null;
        }

        this.server = net.createServer(conf);
        this.clientManager = new ClientManager(this);
        this.router = new Router();
        this.eventHandlers = {};

        beanUtil.getBean('JspApiService').socketSender = (id, code, messageObj) => {
            let targetSocket = this.clientManager.idSockets[id];
            if(targetSocket){
                targetSocket.sendCode(code, messageObj);
            }
        };

        connListener && this.on('connection', connListener);

        this.server.on('connection', function(client){
            _this.clientManager.newClient(client);
        });

        this.server.on('listening', function(){
            logger.info('socket server listening', {name : 'socketServer', listen: _this.server._connectionKey});
            _this.trigger('listening');
        });

        this.server.on('error', function(e){
            logger.error('socket server error', e);
            _this.trigger('error', [e]);
        });

        this.server.on('close', function(){
            logger.error('socket server closed');
            _this.trigger('close');
        });
    }

    on(eventName, handlerFunc){
        if(!eventName || typeof handlerFunc !== 'function'){
            return;
        }
        this.eventHandlers[eventName] = this.eventHandlers[eventName] || [];
        this.eventHandlers[eventName].push(handlerFunc);
    }

    off(eventName, handlerFunc){
        let thisEventHandlers = this.eventHandlers[eventName], idx;
        if(!eventName){
            this.eventHandlers = {};
            return;
        }
        if(!thisEventHandlers){
            return;
        }
        if(!handlerFunc){
            delete this.eventHandlers[eventName];
            return;
        }

        idx = thisEventHandlers.indexOf(handlerFunc);
        idx >= 0 && thisEventHandlers.splice(idx, 1);
    }

    trigger(eventName, args){
        if(!eventName){
            return;
        }
        let thisEventHandlers = this.eventHandlers[eventName], thisServer = this.server;
        if(!thisEventHandlers){
            return;
        }

        thisEventHandlers.forEach(processor => processor.apply(thisServer, args));
    }

    listen(port, callbackFun){
        this.on('listening', callbackFun);
        this.server.listen(port);
    }

    register(urlPattern, handler){
        this.router.registerUrl('socket', urlPattern, handler);
    }
}

module.exports = {
    createServer(conf){
        return new SocketServer(conf || {});
    }
};